package br.com.vilababy.sigvb.dao;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.NoResultException;

import br.com.vilababy.sigvb.SIGVBFactory;
import br.com.vilababy.sigvb.SIGVBUtil;
import br.com.vilababy.sigvb.constantes.SIGVBEnum;
import br.com.vilababy.sigvb.modelo.Aluno;
import br.com.vilababy.sigvb.modelo.Responsavel;

public class AlunoDAO extends AbstractSIGVBDAO<Aluno> {
	
	/**
	 * @author Diego Patrick da Silva Santos
	 */
	@Override
	public int getQuantidadeFiltrados() {
		String consulta = "SELECT COUNT (a) FROM Aluno a";
		this.query = SIGVBFactory.getEM().createQuery(consulta);
		Number totalRegistros = (Number) query.getSingleResult();
		return totalRegistros.intValue();
	}
	
	public int getQuantidadeAlunoComResponsavel() {
		String consulta = "SELECT COUNT (a) FROM Aluno a WHERE size(a.responsaveis) != 0";
		this.query = SIGVBFactory.getEM().createQuery(consulta);
		Number totalRegistros = (Number) query.getSingleResult();
		return totalRegistros.intValue();
	}
	
	public int getQuantidadeConsultados(Aluno aluno) {
		StringBuilder consulta = new StringBuilder("SELECT COUNT (a) FROM Aluno a WHERE ");
		int tamannhoConsulta = consulta.toString().length();
		
		if (aluno.getNome() != null && !aluno.getNome().isEmpty())
			consulta = consulta.append(" UPPER(a.nome) LIKE :nome ");
		
		if (aluno.getApelido() != null && !aluno.getApelido().isEmpty()) {
			consulta = consulta.append(consulta.toString().length() > tamannhoConsulta? " AND": SIGVBEnum.VAZIO.getValor());
			consulta = consulta.append(" UPPER(a.apelido) LIKE :apelido ");
		}
			 
		this.query = SIGVBFactory.getEM().createQuery(consulta.toString());
		if (aluno.getNome() != null && !aluno.getNome().isEmpty())
			this.query.setParameter("nome", "%" + aluno.getNome()  + "%");
		if (aluno.getApelido() != null && !aluno.getApelido().isEmpty()) {
			this.query.setParameter("apelido", "%" + aluno.getApelido() + "%");
		}
		
		Number totalRegistros = (Number) query.getSingleResult();
		return totalRegistros.intValue();
	}
	
	public int getQuantidadeConsultadosAlunoPaisNome(Aluno aluno, Responsavel pai, Responsavel mae) {
		StringBuilder consulta = new StringBuilder("SELECT COUNT (DISTINCT a) FROM Responsavel r INNER JOIN r.aluno AS a WHERE");
		int tamannhoConsulta = consulta.toString().length();
		
		if (pai.getNome() != null && !pai.getNome().isEmpty()) 
			consulta = consulta.append(" (UPPER(r.nome) LIKE :nomePai AND r.relacao = :relacaoPai)");

		if (mae.getNome() != null && !mae.getNome().isEmpty()) {
			consulta = consulta.append(consulta.toString().length() > tamannhoConsulta? " OR": SIGVBEnum.VAZIO.getValor());
			consulta = consulta.append(" (UPPER(r.nome) LIKE :nomeMae AND r.relacao = :relacaoMae)");
		}
		
		if (aluno.getNome() != null && !aluno.getNome().isEmpty()) {
			consulta = consulta.append(consulta.toString().length() > tamannhoConsulta? " AND": SIGVBEnum.VAZIO.getValor());
			consulta = consulta.append(" UPPER(r.aluno.nome) LIKE :nomeAluno");
		}
		
		if (aluno.getApelido() != null && !aluno.getApelido().isEmpty()) {
			consulta = consulta.append(consulta.toString().length() > tamannhoConsulta? " AND": SIGVBEnum.VAZIO.getValor());
			consulta = consulta.append(" UPPER(r.aluno.apelido) LIKE :apelidoAluno");
		}
		
		this.query = SIGVBFactory.getEM().createQuery(consulta.toString());
		
		if (pai.getNome() != null && !pai.getNome().isEmpty()){
			this.query.setParameter("nomePai", "%" + pai.getNome() + "%");
			this.query.setParameter("relacaoPai", pai.getRelacao());
		}
		if (mae.getNome() != null && !mae.getNome().isEmpty()) {
			this.query.setParameter("nomeMae", "%" + mae.getNome() + "%");
			this.query.setParameter("relacaoMae", mae.getRelacao());
		}
		if (aluno.getNome() != null && !aluno.getNome().isEmpty())
			this.query.setParameter("nomeAluno", "%" + aluno.getNome() + "%");
		if (aluno.getApelido() != null && !aluno.getApelido().isEmpty())
			this.query.setParameter("apelidoAluno", aluno.getApelido());

		Number totalRegistros = (Number) this.query.getSingleResult();
		return totalRegistros.intValue();
	}
	
	public int getQuantidadeUsuariosCameraFiltrados() {
		String consulta = "SELECT COUNT (a) FROM Aluno a WHERE a.usuarioCamera IS NOT NULL";
		this.query = SIGVBFactory.getEM().createQuery(consulta);
		Number totalRegistros = (Number) query.getSingleResult();
		return totalRegistros.intValue();
	}

	protected AlunoDAO() {
		if (SIGVBFactory.getEM() == null)
			SIGVBFactory.createEntityManager();
	}
	
	public Aluno consultar(Aluno aluno) {
		String consulta = " FROM Aluno a WHERE a.id = :id";
		this.query = SIGVBFactory.getEM().createQuery(consulta);
		this.query.setParameter("id", aluno.getId());
		
		try {
			return (Aluno) this.query.getSingleResult();
		} catch (NullPointerException nex) {
			System.out.println("Aluno Nulo");
			return new Aluno();
		} catch (ClassCastException cex) {
			System.out.println("Cast na classe aluno não realizado!");
			return new Aluno();
		} catch (NoResultException rex) {
			System.out.println("Não existe resultado para esta consulta!");
			return new Aluno();
		}
	}
	
	@SuppressWarnings("unchecked")
	public List<Aluno> listarAlunosPossuemUsuario(int primeiroRegistro, int totalRegistros) {
		String consulta = " FROM Aluno a WHERE a.usuarioCamera IS NOT NULL ORDER BY a.nome";
		this.query = SIGVBFactory.getEM().createQuery(consulta);
		this.query.setFirstResult(primeiroRegistro);
		this.query.setMaxResults(totalRegistros);
		
		try{
			return (List<Aluno>) this.query.getResultList();
		} catch (NullPointerException nex) {
			System.out.println("Resultado Nulo");
			return new ArrayList<Aluno>();
		} catch (ClassCastException cex) {
			System.out.println("Cast na classe List<Aluno> não realizado!");
			return new ArrayList<Aluno>();
		} catch (NoResultException rex) {
			System.out.println("Não existe resultado para esta consulta!");
			return new ArrayList<Aluno>();
		}
	}
	
	@SuppressWarnings("unchecked")
	public List<Aluno> listarAlunosNaoPossuemUsuario() {
		String consulta = " FROM Aluno a WHERE a.usuarioCamera IS NULL ORDER BY a.nome";
		this.query = SIGVBFactory.getEM().createQuery(consulta);
		
		try{
			return (List<Aluno>) this.query.getResultList();
		} catch (NullPointerException nex) {
			System.out.println("Resultado Nulo");
			return new ArrayList<Aluno>();
		} catch (ClassCastException cex) {
			System.out.println("Cast na classe List<Aluno> não realizado!");
			return new ArrayList<Aluno>();
		} catch (NoResultException rex) {
			System.out.println("Não existe resultado para esta consulta!");
			return new ArrayList<Aluno>();
		}
	}
	
	public List<Aluno> listar() {
		String consulta = "FROM Aluno a ORDER BY a.nome";
		return super.listar(consulta);
	}
	
	@SuppressWarnings("unchecked")
	public List<Aluno> listarPaginacao(int primeiroRegistro, int totalRegistros) {
		String consulta = "FROM Aluno a ORDER BY a.nome";
		this.query = SIGVBFactory.getEM().createQuery(consulta);
		this.query.setFirstResult(primeiroRegistro);
		this.query.setMaxResults(totalRegistros);
		
		try{
			return (List<Aluno>) this.query.getResultList();
		} catch (NullPointerException nex) {
			System.out.println("Resultado Nulo");
			return new ArrayList<Aluno>();
		} catch (ClassCastException cex) {
			System.out.println("Cast na classe List<Aluno> não realizado!");
			return new ArrayList<Aluno>();
		} catch (NoResultException rex) {
			System.out.println("Não existe resultado para esta consulta!");
			return new ArrayList<Aluno>();
		}
	}
	
	@SuppressWarnings("unchecked")
	public List<Aluno> listar(Aluno aluno, int primeiroRegistro, int totalRegistros) {
		StringBuilder consulta = new StringBuilder(" FROM Aluno a WHERE");
		int tamannhoConsulta = consulta.toString().length();
		
		if (aluno.getNome() != null && !aluno.getNome().isEmpty())
			consulta = consulta.append(" UPPER(a.nome) LIKE :nome");
		
		if (aluno.getApelido() != null && !aluno.getApelido().isEmpty()) {
			consulta = consulta.append(consulta.toString().length() > tamannhoConsulta? " AND": SIGVBEnum.VAZIO.getValor());
			consulta = consulta.append(" UPPER(a.apelido) LIKE :apelido ");
		}
			
		this.query = SIGVBFactory.getEM().createQuery(consulta.toString());
		if (aluno.getNome() != null && !aluno.getNome().isEmpty())
			this.query.setParameter("nome", "%" + aluno.getNome()  + "%");
		if (aluno.getApelido() != null && !aluno.getApelido().isEmpty()) {
			this.query.setParameter("apelido", "%" + aluno.getApelido() + "%");
		}
		this.query.setFirstResult(primeiroRegistro);
		this.query.setMaxResults(totalRegistros);
		
		try {
			return  this.query.getResultList();
		} catch (NullPointerException nex) {
			SIGVBUtil.adicionarMensagemErro(SIGVBUtil.getValorMensagem(SIGVBEnum.RESULTADO.getValor()), SIGVBUtil.getValorMensagem(SIGVBEnum.RESULTADO_VAZIO.getValor()));
			return new ArrayList<Aluno>();
		} catch (NoResultException rex) {
			SIGVBUtil.adicionarMensagemErro(SIGVBUtil.getValorMensagem(SIGVBEnum.RESULTADO.getValor()), SIGVBUtil.getValorMensagem(SIGVBEnum.RESULTADO_VAZIO.getValor()));
			return new ArrayList<Aluno>();
		}
	}
	
	@SuppressWarnings("unchecked")
	public List<Aluno> listarAlunoPaisNome(Aluno aluno, Responsavel pai, Responsavel mae) {
		StringBuilder consulta = new StringBuilder("SELECT a FROM Responsavel r INNER JOIN r.aluno AS a WHERE");
		int tamannhoConsulta = consulta.toString().length();
		
		if (pai.getNome() != null && !pai.getNome().isEmpty()) 
			consulta = consulta.append(" (UPPER(r.nome) LIKE :nomePai AND r.relacao = :relacaoPai)");

		if (mae.getNome() != null && !mae.getNome().isEmpty()) {
			consulta = consulta.append(consulta.toString().length() > tamannhoConsulta? " AND": SIGVBEnum.VAZIO.getValor());
			consulta = consulta.append(" (UPPER(r.nome) LIKE :nomeMae AND r.relacao = :relacaoMae)");
		}
		
		if (aluno.getNome() != null && !aluno.getNome().isEmpty()) {
			consulta = consulta.append(consulta.toString().length() > tamannhoConsulta? " AND": SIGVBEnum.VAZIO.getValor());
			consulta = consulta.append(" UPPER(r.aluno.nome) LIKE :nomeAluno");
		}
		
		if (aluno.getApelido() != null && !aluno.getApelido().isEmpty()) {
			consulta = consulta.append(consulta.toString().length() > tamannhoConsulta? " AND": SIGVBEnum.VAZIO.getValor());
			consulta = consulta.append(" UPPER(r.aluno.apelido) LIKE :apelidoAluno");
		}
		
		this.query = SIGVBFactory.getEM().createQuery(consulta.toString());
		
		if (pai.getNome() != null && !pai.getNome().isEmpty()){
			this.query.setParameter("nomePai", "%" + pai.getNome() + "%");
			this.query.setParameter("relacaoPai", pai.getRelacao());
		}
		if (mae.getNome() != null && !mae.getNome().isEmpty()) {
			this.query.setParameter("nomeMae", "%" + mae.getNome() + "%");
			this.query.setParameter("relacaoMae", mae.getRelacao());
		}
		if (aluno.getNome() != null && !aluno.getNome().isEmpty())
			this.query.setParameter("nomeAluno", "%" + aluno.getNome() + "%");
		if (aluno.getApelido() != null && !aluno.getApelido().isEmpty())
			this.query.setParameter("apelidoAluno", aluno.getApelido());

		try {
			return this.query.getResultList();
		} catch (NullPointerException nex) {
			SIGVBUtil.adicionarMensagemErro(SIGVBUtil.getValorMensagem(SIGVBEnum.RESULTADO.getValor()), SIGVBUtil.getValorMensagem(SIGVBEnum.RESULTADO_VAZIO.getValor()));
			return null;
		} catch (NoResultException rex) {
			SIGVBUtil.adicionarMensagemErro(SIGVBUtil.getValorMensagem(SIGVBEnum.RESULTADO.getValor()), SIGVBUtil.getValorMensagem(SIGVBEnum.RESULTADO_VAZIO.getValor()));
			return null;
		}
	}
	
	@SuppressWarnings("unchecked")
	public List<Aluno> listarParcialAlunoPaisNome(Aluno aluno, Responsavel pai, Responsavel mae, int primeiroRegistro, int totalRegistros) {
		StringBuilder consulta = new StringBuilder("SELECT DISTINCT(a) FROM Responsavel r INNER JOIN r.aluno AS a WHERE");
		int tamannhoConsulta = consulta.toString().length();
		
		if (pai.getNome() != null && !pai.getNome().isEmpty()) 
			consulta = consulta.append(" (UPPER(r.nome) LIKE :nomePai AND r.relacao = :relacaoPai)");

		if (mae.getNome() != null && !mae.getNome().isEmpty()) {
			consulta = consulta.append(consulta.toString().length() > tamannhoConsulta? " OR": SIGVBEnum.VAZIO.getValor());
			consulta = consulta.append(" (UPPER(r.nome) LIKE :nomeMae AND r.relacao = :relacaoMae)");
		}
		
		if (aluno.getNome() != null && !aluno.getNome().isEmpty()) {
			consulta = consulta.append(consulta.toString().length() > tamannhoConsulta? " AND": SIGVBEnum.VAZIO.getValor());
			consulta = consulta.append(" UPPER(r.aluno.nome) LIKE :nomeAluno");
		}
		
		if (aluno.getApelido() != null && !aluno.getApelido().isEmpty()) {
			consulta = consulta.append(consulta.toString().length() > tamannhoConsulta? " AND": SIGVBEnum.VAZIO.getValor());
			consulta = consulta.append(" UPPER(r.aluno.apelido) LIKE :apelidoAluno");
		}
		
		this.query = SIGVBFactory.getEM().createQuery(consulta.toString());
		
		if (pai.getNome() != null && !pai.getNome().isEmpty()){
			this.query.setParameter("nomePai", "%" + pai.getNome() + "%");
			this.query.setParameter("relacaoPai", pai.getRelacao());
		}
		if (mae.getNome() != null && !mae.getNome().isEmpty()) {
			this.query.setParameter("nomeMae", "%" + mae.getNome() + "%");
			this.query.setParameter("relacaoMae", mae.getRelacao());
		}
		if (aluno.getNome() != null && !aluno.getNome().isEmpty())
			this.query.setParameter("nomeAluno", "%" + aluno.getNome() + "%");
		if (aluno.getApelido() != null && !aluno.getApelido().isEmpty())
			this.query.setParameter("apelidoAluno", aluno.getApelido());

		this.query.setFirstResult(primeiroRegistro);
		this.query.setMaxResults(totalRegistros);
		
		try {
			return this.query.getResultList();
		} catch (NullPointerException nex) {
			SIGVBUtil.adicionarMensagemErro(SIGVBUtil.getValorMensagem(SIGVBEnum.RESULTADO.getValor()), SIGVBUtil.getValorMensagem(SIGVBEnum.RESULTADO_VAZIO.getValor()));
			return null;
		} catch (NoResultException rex) {
			SIGVBUtil.adicionarMensagemErro(SIGVBUtil.getValorMensagem(SIGVBEnum.RESULTADO.getValor()), SIGVBUtil.getValorMensagem(SIGVBEnum.RESULTADO_VAZIO.getValor()));
			return null;
		}
	}
}
